<?php

namespace App\Services;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;

class FileService
{
    /**
     * 默认存储磁盘
     */
    const DEFAULT_DISK = 'public';
    
    /**
     * 允许的图片格式
     */
    const ALLOWED_IMAGE_TYPES = ['jpeg', 'jpg', 'png', 'gif', 'webp'];
    
    /**
     * 允许的文档格式
     */
    const ALLOWED_DOCUMENT_TYPES = ['pdf', 'doc', 'docx', 'txt'];
    
    /**
     * 允许的Excel格式
     */
    const ALLOWED_EXCEL_TYPES = ['xlsx', 'xls', 'csv'];

    /**
     * 上传文件
     */
    public function uploadFile(UploadedFile $file, string $directory = 'uploads', string $disk = self::DEFAULT_DISK): array
    {
        try {
            $originalName = $file->getClientOriginalName();
            $extension = $file->getClientOriginalExtension();
            $filename = $this->generateUniqueFilename($originalName, $extension);
            $path = $file->storeAs($directory, $filename, $disk);
            
            $result = [
                'success' => true,
                'filename' => $filename,
                'original_name' => $originalName,
                'path' => $path,
                'url' => Storage::disk($disk)->url($path),
                'size' => $file->getSize(),
                'mime_type' => $file->getMimeType(),
                'extension' => $extension,
            ];

            Log::info('File uploaded successfully', $result);
            
            return $result;
        } catch (\Exception $e) {
            Log::error('File upload failed', [
                'original_name' => $file->getClientOriginalName(),
                'error' => $e->getMessage(),
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 上传图片并生成缩略图
     */
    public function uploadImage(UploadedFile $file, string $directory = 'images', array $sizes = []): array
    {
        try {
            // 验证图片格式
            if (!$this->isValidImage($file)) {
                return [
                    'success' => false,
                    'error' => '不支持的图片格式',
                ];
            }

            $originalName = $file->getClientOriginalName();
            $extension = $file->getClientOriginalExtension();
            $filename = $this->generateUniqueFilename($originalName, $extension);
            
            // 上传原图
            $path = $file->storeAs($directory, $filename, self::DEFAULT_DISK);
            
            $result = [
                'success' => true,
                'filename' => $filename,
                'original_name' => $originalName,
                'path' => $path,
                'url' => Storage::disk(self::DEFAULT_DISK)->url($path),
                'size' => $file->getSize(),
                'mime_type' => $file->getMimeType(),
                'extension' => $extension,
                'thumbnails' => [],
            ];

            // 生成缩略图
            if (!empty($sizes)) {
                $thumbnails = $this->generateThumbnails($path, $filename, $sizes);
                $result['thumbnails'] = $thumbnails;
            }

            Log::info('Image uploaded successfully', $result);
            
            return $result;
        } catch (\Exception $e) {
            Log::error('Image upload failed', [
                'original_name' => $file->getClientOriginalName(),
                'error' => $e->getMessage(),
            ]);
            
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * 批量上传文件
     */
    public function uploadMultipleFiles(array $files, string $directory = 'uploads', string $disk = self::DEFAULT_DISK): array
    {
        $results = [];
        $successCount = 0;
        $errorCount = 0;

        foreach ($files as $file) {
            $result = $this->uploadFile($file, $directory, $disk);
            $results[] = $result;
            
            if ($result['success']) {
                $successCount++;
            } else {
                $errorCount++;
            }
        }

        return [
            'results' => $results,
            'success_count' => $successCount,
            'error_count' => $errorCount,
            'total' => count($files),
        ];
    }

    /**
     * 删除文件
     */
    public function deleteFile(string $path, string $disk = self::DEFAULT_DISK): bool
    {
        try {
            if (Storage::disk($disk)->exists($path)) {
                Storage::disk($disk)->delete($path);
                
                Log::info('File deleted successfully', [
                    'path' => $path,
                    'disk' => $disk,
                ]);
                
                return true;
            }
            
            return false;
        } catch (\Exception $e) {
            Log::error('File deletion failed', [
                'path' => $path,
                'disk' => $disk,
                'error' => $e->getMessage(),
            ]);
            
            return false;
        }
    }

    /**
     * 删除多个文件
     */
    public function deleteMultipleFiles(array $paths, string $disk = self::DEFAULT_DISK): array
    {
        $results = [];
        $successCount = 0;
        $errorCount = 0;

        foreach ($paths as $path) {
            $success = $this->deleteFile($path, $disk);
            $results[] = ['path' => $path, 'success' => $success];
            
            if ($success) {
                $successCount++;
            } else {
                $errorCount++;
            }
        }

        return [
            'results' => $results,
            'success_count' => $successCount,
            'error_count' => $errorCount,
            'total' => count($paths),
        ];
    }

    /**
     * 移动文件
     */
    public function moveFile(string $fromPath, string $toPath, string $disk = self::DEFAULT_DISK): bool
    {
        try {
            if (Storage::disk($disk)->exists($fromPath)) {
                Storage::disk($disk)->move($fromPath, $toPath);
                
                Log::info('File moved successfully', [
                    'from' => $fromPath,
                    'to' => $toPath,
                    'disk' => $disk,
                ]);
                
                return true;
            }
            
            return false;
        } catch (\Exception $e) {
            Log::error('File move failed', [
                'from' => $fromPath,
                'to' => $toPath,
                'disk' => $disk,
                'error' => $e->getMessage(),
            ]);
            
            return false;
        }
    }

    /**
     * 复制文件
     */
    public function copyFile(string $fromPath, string $toPath, string $disk = self::DEFAULT_DISK): bool
    {
        try {
            if (Storage::disk($disk)->exists($fromPath)) {
                Storage::disk($disk)->copy($fromPath, $toPath);
                
                Log::info('File copied successfully', [
                    'from' => $fromPath,
                    'to' => $toPath,
                    'disk' => $disk,
                ]);
                
                return true;
            }
            
            return false;
        } catch (\Exception $e) {
            Log::error('File copy failed', [
                'from' => $fromPath,
                'to' => $toPath,
                'disk' => $disk,
                'error' => $e->getMessage(),
            ]);
            
            return false;
        }
    }

    /**
     * 获取文件信息
     */
    public function getFileInfo(string $path, string $disk = self::DEFAULT_DISK): ?array
    {
        try {
            if (!Storage::disk($disk)->exists($path)) {
                return null;
            }

            $size = Storage::disk($disk)->size($path);
            $mimeType = Storage::disk($disk)->mimeType($path);
            $lastModified = Storage::disk($disk)->lastModified($path);

            return [
                'path' => $path,
                'url' => Storage::disk($disk)->url($path),
                'size' => $size,
                'mime_type' => $mimeType,
                'last_modified' => date('Y-m-d H:i:s', $lastModified),
                'extension' => pathinfo($path, PATHINFO_EXTENSION),
            ];
        } catch (\Exception $e) {
            Log::error('Failed to get file info', [
                'path' => $path,
                'disk' => $disk,
                'error' => $e->getMessage(),
            ]);
            
            return null;
        }
    }

    /**
     * 生成缩略图
     */
    public function generateThumbnails(string $imagePath, string $filename, array $sizes): array
    {
        $thumbnails = [];
        
        try {
            $fullPath = Storage::disk(self::DEFAULT_DISK)->path($imagePath);
            $image = Image::make($fullPath);
            
            foreach ($sizes as $size) {
                $width = $size['width'] ?? 300;
                $height = $size['height'] ?? 300;
                $suffix = $size['suffix'] ?? "_{$width}x{$height}";
                
                $thumbnailFilename = $this->addSuffixToFilename($filename, $suffix);
                $thumbnailPath = dirname($imagePath) . '/' . $thumbnailFilename;
                
                $thumbnail = clone $image;
                $thumbnail->resize($width, $height, function ($constraint) {
                    $constraint->aspectRatio();
                    $constraint->upsize();
                });
                
                $thumbnail->save(Storage::disk(self::DEFAULT_DISK)->path($thumbnailPath));
                
                $thumbnails[] = [
                    'size' => "{$width}x{$height}",
                    'filename' => $thumbnailFilename,
                    'path' => $thumbnailPath,
                    'url' => Storage::disk(self::DEFAULT_DISK)->url($thumbnailPath),
                ];
            }
            
            Log::info('Thumbnails generated successfully', [
                'image_path' => $imagePath,
                'thumbnails' => $thumbnails,
            ]);
            
        } catch (\Exception $e) {
            Log::error('Thumbnail generation failed', [
                'image_path' => $imagePath,
                'error' => $e->getMessage(),
            ]);
        }
        
        return $thumbnails;
    }

    /**
     * 压缩图片
     */
    public function compressImage(string $imagePath, int $quality = 80): bool
    {
        try {
            $fullPath = Storage::disk(self::DEFAULT_DISK)->path($imagePath);
            $image = Image::make($fullPath);
            
            $image->save($fullPath, $quality);
            
            Log::info('Image compressed successfully', [
                'image_path' => $imagePath,
                'quality' => $quality,
            ]);
            
            return true;
        } catch (\Exception $e) {
            Log::error('Image compression failed', [
                'image_path' => $imagePath,
                'error' => $e->getMessage(),
            ]);
            
            return false;
        }
    }

    /**
     * 清理临时文件
     */
    public function cleanupTempFiles(int $hours = 24): int
    {
        $tempDirectory = 'temp';
        $files = Storage::disk(self::DEFAULT_DISK)->files($tempDirectory);
        $deletedCount = 0;
        
        foreach ($files as $file) {
            $lastModified = Storage::disk(self::DEFAULT_DISK)->lastModified($file);
            $ageInHours = (time() - $lastModified) / 3600;
            
            if ($ageInHours > $hours) {
                if ($this->deleteFile($file)) {
                    $deletedCount++;
                }
            }
        }
        
        Log::info('Temp files cleaned up', [
            'deleted_count' => $deletedCount,
            'hours' => $hours,
        ]);
        
        return $deletedCount;
    }

    /**
     * 获取存储使用情况
     */
    public function getStorageUsage(string $disk = self::DEFAULT_DISK): array
    {
        try {
            $directories = Storage::disk($disk)->directories();
            $totalSize = 0;
            $fileCount = 0;
            $directoryStats = [];
            
            foreach ($directories as $directory) {
                $files = Storage::disk($disk)->allFiles($directory);
                $directorySize = 0;
                
                foreach ($files as $file) {
                    $directorySize += Storage::disk($disk)->size($file);
                }
                
                $directoryStats[$directory] = [
                    'size' => $directorySize,
                    'file_count' => count($files),
                ];
                
                $totalSize += $directorySize;
                $fileCount += count($files);
            }
            
            return [
                'total_size' => $totalSize,
                'total_size_mb' => round($totalSize / 1024 / 1024, 2),
                'file_count' => $fileCount,
                'directory_stats' => $directoryStats,
            ];
        } catch (\Exception $e) {
            Log::error('Failed to get storage usage', [
                'disk' => $disk,
                'error' => $e->getMessage(),
            ]);
            
            return [
                'total_size' => 0,
                'total_size_mb' => 0,
                'file_count' => 0,
                'directory_stats' => [],
            ];
        }
    }

    /**
     * 验证图片文件
     */
    private function isValidImage(UploadedFile $file): bool
    {
        $extension = strtolower($file->getClientOriginalExtension());
        return in_array($extension, self::ALLOWED_IMAGE_TYPES);
    }

    /**
     * 验证文档文件
     */
    public function isValidDocument(UploadedFile $file): bool
    {
        $extension = strtolower($file->getClientOriginalExtension());
        return in_array($extension, self::ALLOWED_DOCUMENT_TYPES);
    }

    /**
     * 验证Excel文件
     */
    public function isValidExcel(UploadedFile $file): bool
    {
        $extension = strtolower($file->getClientOriginalExtension());
        return in_array($extension, self::ALLOWED_EXCEL_TYPES);
    }

    /**
     * 生成唯一文件名
     */
    private function generateUniqueFilename(string $originalName, string $extension): string
    {
        $name = pathinfo($originalName, PATHINFO_FILENAME);
        $name = Str::slug($name);
        $timestamp = time();
        $random = Str::random(8);
        
        return "{$name}_{$timestamp}_{$random}.{$extension}";
    }

    /**
     * 为文件名添加后缀
     */
    private function addSuffixToFilename(string $filename, string $suffix): string
    {
        $pathInfo = pathinfo($filename);
        return $pathInfo['filename'] . $suffix . '.' . $pathInfo['extension'];
    }

    /**
     * 获取文件类型
     */
    public function getFileType(string $mimeType): string
    {
        if (str_starts_with($mimeType, 'image/')) {
            return 'image';
        }
        
        if (str_starts_with($mimeType, 'video/')) {
            return 'video';
        }
        
        if (str_starts_with($mimeType, 'audio/')) {
            return 'audio';
        }
        
        if (in_array($mimeType, [
            'application/pdf',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'text/plain',
        ])) {
            return 'document';
        }
        
        if (in_array($mimeType, [
            'application/vnd.ms-excel',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'text/csv',
        ])) {
            return 'excel';
        }
        
        return 'other';
    }
}
